import Notifier from "./notifer/Notifier";
import SocketManager from "./socket/SocketManager";

export class core {

    public static debug = true;  

    /** 全局通知 */
    public static readonly notifier = Notifier;

    /** Socket */
    public static readonly socket = SocketManager.instance;

    public static readonly transfer = true;

    /** 中介者 */
    public static get mediators(): IMediator[] { return this._mediators; }
    private static _mediators: IMediator[] = [];

    private static $map: Map<IProto, protobufId> = new Map();
    /** 
     * 注册全局通知
     * @param type  通知类型
     * @param handler  回调函数
     * @param observer  观察者(回调上下文)
     * @param priority  当多个回调存在时的优先级(默认=0,数值越大越先触发)
     *  */
     public static on(type: NotifyType, handler: NotifyHandler, observer?: any, priority: number = 0): void {
        Notifier.attach(type, handler, observer, priority);
    }

    /** 
     * 注销全局通知
     * @param type  通知类型
     * @param handler  回调函数
     * @param observer  观察者(回调上下文)
     * @description 只有当handler和observer与注册时一一对应注销才能生效
     *  */
    public static off(type: NotifyType, handler: NotifyHandler, observer?: any): void {
        Notifier.detach(type, handler, observer);
    }

    /** 
     * 发送全局通知
     * @param type  通知类型
     * @param data  通知内容罗列
     *  */
    public static notify(type: NotifyType, ...data: any[]): void {
        Notifier.dispatch(type, ...data);
    }

    /** 
     * 卸载观察者身上的所有通知
     * @param observer  观察者
     *  */
    public static unload(observer: any): void {
        Notifier.unload(observer);
    }

    /** 
     * 卸载某个类型的所有通知
     * @param type  通知类型
     *  */
    public static clear(type: NotifyType): void {
        Notifier.clear(type);
    }

    /** 
     * 注册网络消息(将消息号对应消息体)
     * @param routers  消息路由罗列
     *  */
    public static register(...routers: IProtoRouter[]): void {
        routers.forEach(router => {
            let { name, msgId,gameId, serviceNo, Proto } = router;
            let protoId: number = msgId;
            this.$map.set(Proto, protoId);
            // core.socket.registerSingleMsg(protoId, gameId, Proto);
        });
    }

    
    /** 
     * 注册网络消息
     * @param routers  消息路由罗列
     *  */
     public static send<P extends IProto>(proto: P, data: ProtoData<P>): void {
        if (this.$map.has(proto)) {
            let pid: protobufId = this.$map.get(proto);
            if (this.debug)
                console.debug(`${this.transfer ? '' : '模拟'}发送=>`, pid, data ?? {});
            // if (this.transfer) this.socket.sendMessage(pid, data ?? {});
        } else console.error("发送未注册protobuf:", proto);

    }

    /** 
     * 将网络消息直接路由到观察者
     * @param proto  Message类型
     * @param handler  回调函数
     * @param observer  观察者(回调上下文)
     * @param priority  当多个回调存在时的优先级(默认=0,数值越大越先触发)
     *  */
    public static route<P extends IProto>(proto: P, handler: (msg?: ProtoData<P>) => any, observer?: any, priority: number = 0): void {
        if (this.$map.has(proto)) {
            let pid: protobufId = this.$map.get(proto);
            this.on(pid, handler, observer, priority);
        } else console.error("路由未注册protobuf:", proto);
    }

    /** 
     * 注销网络消息的路由
     * @param proto  Message类型
     * @param handler  回调函数
     * @param observer  观察者(回调上下文)
     * @description 只有当handler和observer与注册时一一对应注销才能生效
     *  */
    public static unroute<P extends IProto>(proto: P, handler: (msg?: ProtoData<P>) => any, observer?: any): void {
        if (this.$map.has(proto)) {
            let pid = this.$map.get(proto);
            this.off(pid, handler, observer);
        } else console.error("卸载未注册protobuf:", proto);
    }

    /** 
     * 通过指定类型获取中介者
     * @param Mediator  中介者类
     * @return 当前的中介者
     *  */
    public static mediator<M extends IMediator>(Mediator: Clazz<M>): M | null {
        if (!Mediator) return null;
        for (let m of this._mediators) {
            if (m instanceof Mediator) return m;
        }
        return null;
    }

}